"""Auth API endpoints"""
from functools import cache
from typing import List, Optional

from fastapi import APIRouter, Depends, Header, HTTPException, Query
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer

from dbgpt.component import SystemApp
from dbgpt.util import PaginationResult
from dbgpt_serve.core import Result

from ..config import SERVE_SERVICE_COMPONENT_NAME, ServeConfig
from ..service.service import Service
from .schemas import (
    LoginRequest,
    LoginResponse,
    MenuRequest,
    MenuResponse,
    RoleRequest,
    RoleResponse,
    UserRequest,
    UserResponse,
)

router = APIRouter()

global_system_app: Optional[SystemApp] = None


def get_service() -> Service:
    """Get service instance"""
    return global_system_app.get_component(SERVE_SERVICE_COMPONENT_NAME, Service)


get_bearer_token = HTTPBearer(auto_error=False)


@cache
def _parse_api_keys(api_keys: str) -> List[str]:
    """Parse API keys"""
    if not api_keys:
        return []
    return [key.strip() for key in api_keys.split(",")]


async def check_api_key(
    auth: Optional[HTTPAuthorizationCredentials] = Depends(get_bearer_token),
    service: Service = Depends(get_service),
) -> dict:
    """Check API key or JWT token"""
    if not auth:
        raise HTTPException(status_code=401, detail="Not authenticated")

    token = auth.credentials

    # Verify JWT token
    payload = service.verify_token(token)
    if not payload:
        raise HTTPException(status_code=401, detail="Invalid or expired token")

    return payload


def init_endpoints(system_app: SystemApp, config: ServeConfig) -> None:
    """Initialize endpoints"""
    global global_system_app
    system_app.register(Service, config=config)
    global_system_app = system_app


# ========================================
# Auth Endpoints
# ========================================
@router.post("/auth/login", response_model=Result[LoginResponse])
async def login(
    request: LoginRequest,
    service: Service = Depends(get_service),
):
    """User login"""
    try:
        result = service.login(request)
        return Result.succ(result)
    except ValueError as e:
        return Result.failed(msg=str(e), err_code="E001")
    except Exception as e:
        return Result.failed(msg=f"Login failed: {str(e)}", err_code="E500")


@router.post("/auth/logout", response_model=Result[bool])
async def logout(
    current_user: dict = Depends(check_api_key),
):
    """User logout"""
    # In stateless JWT, logout is handled by client removing token
    return Result.succ(True)


@router.get("/auth/current_user", response_model=Result[UserResponse])
async def get_current_user(
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Get current user info"""
    user_id = current_user.get("user_id")
    user = service.get_user_by_id(user_id)
    if not user:
        return Result.failed(msg="User not found", err_code="E404")
    return Result.succ(user)


# ========================================
# User Management Endpoints
# ========================================
@router.post("/users", response_model=Result[UserResponse])
async def create_user(
    request: UserRequest,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Create user"""
    try:
        result = service.create_user(request)
        return Result.succ(result)
    except ValueError as e:
        return Result.failed(msg=str(e), err_code="E001")
    except Exception as e:
        return Result.failed(msg=f"Create user failed: {str(e)}", err_code="E500")


@router.put("/users/{user_id}", response_model=Result[UserResponse])
async def update_user(
    user_id: int,
    request: UserRequest,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Update user"""
    try:
        result = service.update_user(user_id, request)
        return Result.succ(result)
    except ValueError as e:
        return Result.failed(msg=str(e), err_code="E001")
    except Exception as e:
        return Result.failed(msg=f"Update user failed: {str(e)}", err_code="E500")


@router.delete("/users/{user_id}", response_model=Result[bool])
async def delete_user(
    user_id: int,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Delete user"""
    result = service.delete_user(user_id)
    return Result.succ(result)


@router.get("/users/{user_id}", response_model=Result[UserResponse])
async def get_user(
    user_id: int,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Get user by ID"""
    user = service.get_user_by_id(user_id)
    if not user:
        return Result.failed(msg="User not found", err_code="E404")
    return Result.succ(user)


@router.get("/users", response_model=Result[PaginationResult[UserResponse]])
async def list_users(
    page: int = Query(1, description="Page number"),
    page_size: int = Query(20, description="Page size"),
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """List users"""
    result = service.list_users(page, page_size)
    return Result.succ(result)


# ========================================
# Role Management Endpoints
# ========================================
@router.post("/roles", response_model=Result[RoleResponse])
async def create_role(
    request: RoleRequest,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Create role"""
    try:
        result = service.create_role(request)
        return Result.succ(result)
    except ValueError as e:
        return Result.failed(msg=str(e), err_code="E001")
    except Exception as e:
        return Result.failed(msg=f"Create role failed: {str(e)}", err_code="E500")


@router.put("/roles/{role_id}", response_model=Result[RoleResponse])
async def update_role(
    role_id: int,
    request: RoleRequest,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Update role"""
    try:
        result = service.update_role(role_id, request)
        return Result.succ(result)
    except ValueError as e:
        return Result.failed(msg=str(e), err_code="E001")
    except Exception as e:
        return Result.failed(msg=f"Update role failed: {str(e)}", err_code="E500")


@router.delete("/roles/{role_id}", response_model=Result[bool])
async def delete_role(
    role_id: int,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Delete role"""
    result = service.delete_role(role_id)
    return Result.succ(result)


@router.get("/roles", response_model=Result[PaginationResult[RoleResponse]])
async def list_roles(
    page: int = Query(1, description="Page number"),
    page_size: int = Query(20, description="Page size"),
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """List roles"""
    result = service.list_roles(page, page_size)
    return Result.succ(result)


# ========================================
# Menu Management Endpoints
# ========================================
@router.post("/menus", response_model=Result[MenuResponse])
async def create_menu(
    request: MenuRequest,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Create menu"""
    try:
        result = service.create_menu(request)
        return Result.succ(result)
    except ValueError as e:
        return Result.failed(msg=str(e), err_code="E001")
    except Exception as e:
        return Result.failed(msg=f"Create menu failed: {str(e)}", err_code="E500")


@router.put("/menus/{menu_id}", response_model=Result[MenuResponse])
async def update_menu(
    menu_id: int,
    request: MenuRequest,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Update menu"""
    try:
        result = service.update_menu(menu_id, request)
        return Result.succ(result)
    except ValueError as e:
        return Result.failed(msg=str(e), err_code="E001")
    except Exception as e:
        return Result.failed(msg=f"Update menu failed: {str(e)}", err_code="E500")


@router.delete("/menus/{menu_id}", response_model=Result[bool])
async def delete_menu(
    menu_id: int,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Delete menu"""
    result = service.delete_menu(menu_id)
    return Result.succ(result)


@router.get("/menus/tree", response_model=Result[List[MenuResponse]])
async def get_menu_tree(
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Get menu tree"""
    result = service.get_menu_tree()
    return Result.succ(result)


@router.get("/menus/user/{user_id}", response_model=Result[List[MenuResponse]])
async def get_user_menus(
    user_id: int,
    current_user: dict = Depends(check_api_key),
    service: Service = Depends(get_service),
):
    """Get user menus"""
    result = service.get_user_menus(user_id)
    return Result.succ(result)
